import { Injectable } from '@nestjs/common';
import { CreateTokenDto } from './dto/create-token.dto';
import { Token } from './token.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, In } from 'typeorm';

import { WechatApp } from '../libs/utils';

const axios = require('axios').default;

import { Qiniu } from '../libs/config';
const qiniu = require('qiniu');
const accessKey = Qiniu.ak;
const secretKey = Qiniu.sk;
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);

const options = {
  scope: 'wemarketing',
  expires: 3600 * 2,
};
let config = new qiniu.conf.Config();
// 空间对应的机房
config.zone = qiniu.zone.Zone_z1;

@Injectable()
export class TokenService {
  constructor(
    @InjectRepository(Token)
    private tokenRepository: Repository<Token>,
  ) {}

  // 增加
  async create(createTokenDto: CreateTokenDto): Promise<any> {
    const { createdAt, type, time = Date.now() } = createTokenDto;
    createTokenDto.createdAt = createdAt || new Date();
    createTokenDto.updatedAt = new Date();
    createTokenDto.time = String(Date.now());

    const tokenItem = await this.findOneById(type);

    const formUploader = new qiniu.form_up.FormUploader(config);
    const putExtra = new qiniu.form_up.PutExtra();

    if (tokenItem) {
      const { id, time: timeItem, token } = tokenItem;
      console.log('time', time);
      console.log('timeItem', timeItem);
      if ((Number(time) - Number(timeItem)) / 1000 >= 3600 * 2 - 60 * 4) {
        const putPolicy = new qiniu.rs.PutPolicy(options);
        const uploadToken = putPolicy.uploadToken(mac);

        createTokenDto.token = uploadToken;

        await this.update({ id, updateTokenDto: createTokenDto });
        return {
          uploadToken,
          formUploader,
          putExtra,
        };
      } else {
        return {
          uploadToken: token,
          formUploader,
          putExtra,
        };
      }
    } else {
      delete createTokenDto.id;
      const putPolicy = new qiniu.rs.PutPolicy(options);
      const uploadToken = putPolicy.uploadToken(mac);
      createTokenDto.token = uploadToken;

      await this.tokenRepository.save(createTokenDto);

      return {
        uploadToken,
        formUploader,
        putExtra,
      };
    }
  }

  async createWechat(createTokenDto: CreateTokenDto): Promise<any> {
    const { createdAt, type, time } = createTokenDto;
    createTokenDto.createdAt = createdAt || new Date();
    createTokenDto.updatedAt = new Date();
    createTokenDto.time = String(Date.now());

    const tokenItem = await this.findOneById(type);

    if (tokenItem) {
      const { id, time: timeItem, token } = tokenItem;

      console.log('time', time);
      console.log('timeItem', timeItem);

      if ((Number(time) - Number(timeItem)) / 1000 >= 3600 * 2 - 60 * 4) {
        const accessToken = await axios({
          url: `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${WechatApp.appId}&secret=${WechatApp.appSecret}`,
        });
        const data = accessToken.data || {};
        const { access_token } = data;
        createTokenDto.token = access_token;

        await this.update({ id, updateTokenDto: createTokenDto });
        return access_token;
      } else {
        return token;
      }
    } else {
      delete createTokenDto.id;

      const accessToken = await axios({
        url: `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${WechatApp.appId}&secret=${WechatApp.appSecret}`,
      });
      const data = accessToken.data || {};
      const { access_token } = data;
      createTokenDto.token = access_token;

      await this.tokenRepository.save(createTokenDto);

      return access_token;
    }
  }

  // 更新
  async update(updateTokenData): Promise<any> {
    const { id, updateTokenDto } = updateTokenData;
    updateTokenDto.updatedAt = new Date();

    return await this.tokenRepository.update(id, updateTokenDto);
  }

  // 列表
  async findAll(query: any): Promise<any> {
    const { keyword, pageId, page = 1, limit = 10 } = query;
    const skip = (page - 1) * limit;

    let params = {
      skip,
      take: limit,
    };

    let whereParams = {};

    if (keyword) {
      whereParams = [
        {
          name: Like(`%${keyword}%`),
        },
        {
          phone: Like(`%${keyword}%`),
        },
      ];
    }
    if (pageId) {
      const ids = Array.isArray(pageId) ? pageId : [pageId];

      whereParams = keyword
        ? [
            {
              pageId: In(ids),
              name: Like(`%${keyword}%`),
            },
            {
              pageId: In(ids),
              phone: Like(`%${keyword}%`),
            },
          ]
        : { pageId: In(ids) };
    }

    params = Object.assign(
      params,
      {
        where: whereParams,
      },
      {
        order: {
          updatedAt: 'DESC',
        },
      },
    );

    const [data, total] = await this.tokenRepository.findAndCount(params);

    return {
      total,
      data,
    };
  }

  // 根据 type 查找
  async findOneById(id: string): Promise<any> {
    return this.tokenRepository
      .createQueryBuilder()
      .where([{ type: id }])
      .getOne();
  }
}
